<template>
  <div style="display: inline-block">
    <el-upload
      ref="upload"
      :action="action"
      :name="name"
      :accept="accept"
      :disabled="!ishowButton"
      :data="{ }"
      :before-upload="handleBeforeUpLoad"
      :on-remove="handleRemove"
      :on-error="handleError"
      :on-success="handleFileSuccess"
      :http-request="uploadRequest"
      :show-file-list="false"
      :file-list="fileList"
    >
      <slot>
        <div class="upload-list__item">
          <span
            v-if="imageUrl && ishowButton"
            class="upload-list__item-actions"
            :style="{ width: size + 'px', height: size + 'px', lineHeight: size + 'px' }"
          >
            <i class="el-icon-edit" />
            <i class="el-icon-zoom-in"  @click.stop="viewImg"/>
            <i class="el-icon-delete" @click.stop="handleRemove" />
          </span>
          <el-progress
            v-if="f_status"
            :type="'circle'"
            :width="size"
            :stroke-width="6"
            :status="f_status === 'uploading' ? null : f_status"
            :percentage="parsePercentage(percentage, f_status)"
          />
          <template v-else>
            <el-image v-if="imageUrl" :src="imageUrl" :style="imgStyle" class="imageBor" :fit="'contain'" @click="viewImg">
              <div slot="error" class="image-slot">
                <i class="el-icon-picture-outline"></i>
              </div>
            </el-image>
            <div v-else>
              <div class="upload-icon" :style="imgStyle">
                <span v-if="ishowButton" :class="icon" :style="iconStyle" />
                <img v-else :src="img_default" alt="默认" />
              </div>
            </div>
          </template>
        </div>
      </slot>
    </el-upload>
    <el-image-viewer v-if="dialogViewFileImg" :on-close="closeViewer" :z-index="19940306" :url-list="viewerImgList" />
  </div>
</template>
<script>
//  GOODS("商品"), CONTENT("内容"), CATEGORY("类别"), SUPPLIER("供应商"), AVATAR("头像"), SYSTEM("系统"), OTHERS("其他"), CHAT("聊天"), LIVE("直播");
// 上传文件组件
import img_default from '@/assets/images/blank/default.png'
import axios from 'axios'
import { mediaType, fileType } from './const/file'
import { parseTime } from '@/utils'
import readFileSizeUnit from './mix/readFileSizeUnit/index.js'
import emitter from 'element-ui/src/mixins/emitter'
import ElImageViewer from '@/components/ElImageViewer/index.vue'
import { policy } from '@/api/oss'
export default {
  components: { ElImageViewer },
  mixins: [readFileSizeUnit, emitter],
  props: {
    value: {
      type: [String, Array],
      default() {
        return ''
      }
    },
    ishowButton: {
      type: Boolean,
      default: true
    },
    name: {
      type: String,
      default: 'imageFile'
    },
    // 上传的媒体类型
    acceptType: {
      type: String,
      default: 'IMG'
    },
    fileSize: {
      type: Number,
      default: 1
    },
    imgStyle: {
      type: String,
      default: 'width: 100px; height: 100px;line-height: 100px;'
    },
    icon: {
      type: String,
      default: 'el-icon-plus'
    },
    iconStyle: {
      type: String,
      default: 'font-size:20px'
    },
    size: {
      type: Number,
      default: 100
    }
  },
  data() {
    var token = this.$store.state.user.token
    return {
      token,
      img_default,
      fileList: [],
      imageUrl: '',
      action: this.$store.state.app.upload_url_file,
      accept: '.gif, .jpg, .jpeg, .png, .bmp, .GIF, .JPG, .PNG',
      f_status: '',
      percentage: 0,
      dialogViewFileImg: false,
      viewerImgList: [],
      policyData: {}
    }
  },
  watch: {
    value: {
      handler(newVal) {
        if (Array.isArray(newVal) && newVal.length > 0) {
          this.imageUrl = newVal[0].url || newVal[0].imgurl
          this.fileList = newVal
        } else if (newVal) {
          this.imageUrl = newVal
          this.fileList = [{ url: newVal }]
        } else {
          this.imageUrl = ''
          this.fileList = []
        }
      },
      immediate: true
    },
    acceptType(val) {
      const _l = mediaType.filter(item => item.value === val)
      this.accept = _l.length === 0 ? '*' : _l[0].accept
    },
    imageUrl: {
      handler(v) {
        this.dispatch('ElFormItem', 'el.form.change', v)
      },
      immediate: true,
      deep: true
    }
  },
  methods: {
    /* 查看附件 */
    viewImg() {
      this.dialogViewFileImg = true
      this.viewerImgList.push(this.imageUrl)
    },
    closeViewer() {
      this.dialogViewFileImg = false
    },
    handleError(err) {
      const msg = JSON.stringify(err)
      if (msg.toLowerCase().includes('401') || msg.toLowerCase().includes('invalid_token')) {
        this.$router.push('/login')
      }
    },
    parsePercentage(val, status) {
      if (status === 'success') {
        return 100
      }
      if (status === 'exception') {
        return 0
      }
      if (typeof val !== 'number') return 0
      return parseInt(val, 10)
    },
    uploadRequest(option) {
      const self = this
      const file = option.file
      const type = file.type
      const size = file.size
      const pos = file.name.lastIndexOf('.')
      const filename = file.name.substring(0, pos)
      const extendName = file.name.substring(pos + 1)

      var param = new window.FormData()
      param.append('file', file, file.name)
      const { policy, signature, ossaccessKeyId, key, dir, host } = this.policyData
      param.append('policy', policy)
      param.append('signature', signature)
      param.append('ossaccessKeyId', ossaccessKeyId)
      param.append('key', key)
      param.append('dir', dir)
      param.append('host', host)
      axios
        .post(this.action, param, {
          headers: {
            'Content-Type': 'application/json;charset=UTF-8',
            Authorization: this.token
          },
          onUploadProgress(p) {
            self.percentage = 99 * (p.loaded / p.total)
          }
        })
        .then(r => {
          self.percentage = 100
          self.f_status = 'success'
          setTimeout(() => {
            self.f_status = ''
          }, 1500)
          option.onSuccess({ filename, extendName, size, type, ...r.data })
        })
        .catch(e => {
          self.f_status = 'exception'
          option.onError(e)
        })
    },
    handleFileSuccess(res, file) {
      var t = file.response.type.indexOf('image') !== -1
      this.fileList = [
        {
          uid: file.uid,
          filePath: res.data,
          fileName: res.filename,
          creater: this.$store.state.user.name,
          createTime: parseTime(new Date(), '{y}{m}{d}'),
          fileSize: this.readFileSizeUnit(file.size),
          type: file.response.type,
          isimage: t,
          imgurl: res.data,
          icon: t ? '' : 'file-file'
        }
      ]
      this.imageUrl = res.data
      this.$emit('input', res.data)
      this.$emit('change', res.data)
    },
    setFileIcon(v) {
      let fileExtend = ''
      var name = v.fileName || v.name
      if (name) {
        fileExtend = name.substring(name.lastIndexOf('.') + 1).toLowerCase()
      } else {
        fileExtend = 'file'
      }
      var sc = find(fileType, o => {
        return o.label.toLowerCase() === fileExtend
      })
      if (sc) {
        v.icon = sc.value
      }
      return v.icon
    },
    handleRemove(file, fileList) {
      this.imageUrl = ''
      this.$emit('input', '')
      this.$emit('remove')
    },
    async handleBeforeUpLoad(file) {
      this.percentage = 0
      this.f_status = 'uploading'
      var t = file.type.indexOf('image') !== -1
      if (!t) {
        this.$message.error(`只能上传图片！`)
        return false
      }
      this.fileList = [
        ...this.fileList,
        {
          uid: file.uid,
          imgurl: URL.createObjectURL(file),
          isimage: t,
          icon: t ? '' : 'file-file'
        }
      ]
      var uid = file.uid
      return new Promise((resolve, reject) => {
        this.transformFile(file)
          .then(res => {
            //装换之后 file的uid丢失
            res.uid = uid
            resolve(res)
            // reject(res)
          })
          .catch(error => {
            reject(error)
          })
      })
    },
    getpolicy() {
      const _self = this
      return new Promise((resolve, reject) => {
        policy()
          .then(response => {
            _self.policyData.policy = response.data.policy
            _self.policyData.signature = response.data.signature
            _self.policyData.ossaccessKeyId = response.data.accessKeyId
            _self.policyData.key = response.data.dir
            _self.policyData.dir = response.data.dir
            _self.policyData.host = response.data.host
            resolve(true)
          })
          .catch(err => {
            reject(false)
          })
      })
    }, //转换文件 添加水印
    transformFile(file) {
      //promise执行多步操作非常好用，这个过程是有一定的顺序的，你必须保证上一步完成，才能顺利进行下一步。
      //有两个参数 resolve同意的意思 reject拒绝的意思
      return new Promise(resolve => {
        const reader = new FileReader() //创建读取文件对象
        reader.readAsDataURL(file) //调用方法转base64
        reader.onload = () => {
          //文件读取成功完成的触发
          const canvas = document.createElement('canvas') //新建canvas 画布
          const img = document.createElement('img') //新建一个img标签
          img.src = reader.result //读取结果 下载图片
          img.onload = () => {
            //绑定事件 下载完成
            const ctx = canvas.getContext('2d') //获取画笔对象
            let width = img.width //图片的宽高
            let height = img.height
            canvas.width = width //画布的宽高
            canvas.height = height
            ctx.drawImage(img, 0, 0, width, height) //绘制图像 图片大小没变
            ctx.fillStyle = '#fff' // 设置填充字号和字体，样式
            ctx.textBaseline = 'middle'
            // // 设置右对齐
            // ctx.textAlign = 'right'
            // // ctx.rotate((0 * Math.PI) / 180) //旋转画笔 角度
            ctx.globalAlpha = 0.6 //透明度
            ctx.font="16px Georgia";
            ctx.fillText('powered by Jihepai', 0, height - 20, width)
            /* canvas.toBlob(resolve); */
            //压缩图片质量 范围 0~1
            let dataUrl = canvas.toDataURL('image/jpeg', 1) //输出压缩后的base64
            //执行下一步操作 将裁剪base64的图片转换为file文件
            resolve(this.dataURLtoFile(dataUrl, file.name))
          }
        }
      })
    },
    // 将裁剪base64的图片转换为file文件
    dataURLtoFile(dataurl, filename) {
      let arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    }
  }
}
</script>
<style lang="scss" scoped>
@import './style/uploadList.scss';
</style>
